ARD2  RC2
Airbag Reference Demonstrator using MPC5604P
freemaster_can.c
Go to the documentation of this file.
00001 /******************************************************************************
00002 *
00003 * Freescale Semiconductor Inc.
00004 * (c) Copyright 2004-2010 Freescale Semiconductor
00005 * ALL RIGHTS RESERVED.
00006 *
00007 ****************************************************************************/
00019 #include "freemaster.h"
00020 #include "freemaster_private.h"
00021 #include "freemaster_protocol.h"
00022 
00023 #if FMSTR_USE_CAN
00024 
00025 /***********************************
00026 *  CAN low-level access macros 
00027 ***********************************/
00028 
00029 #if FMSTR_USE_MSCAN
00030 
00031     #define FMSTR_CAN_ETXI() FMSTR_MSCAN_ETXI() 
00032     #define FMSTR_CAN_DTXI() FMSTR_MSCAN_DTXI() 
00033     #define FMSTR_CAN_ERXI() FMSTR_MSCAN_ERXI() 
00034     #define FMSTR_CAN_DRXI() FMSTR_MSCAN_DRXI() 
00035     #define FMSTR_CAN_TEST_RXFLG() FMSTR_MSCAN_TEST_RXFLG() 
00036     #define FMSTR_CAN_CLEAR_RXFLG() FMSTR_MSCAN_CLEAR_RXFLG() 
00037     #define FMSTR_CAN_TEST_TXFLG() FMSTR_MSCAN_TEST_TXFLG() 
00038     #define FMSTR_CAN_GET_MBSTATUS() FMSTR_MSCAN_GET_MBSTATUS()
00039     #define FMSTR_CAN_MAKEIDR0(id) FMSTR_MSCAN_MAKEIDR0(id) 
00040     #define FMSTR_CAN_MAKEIDR1(id) FMSTR_MSCAN_MAKEIDR1(id) 
00041     #define FMSTR_CAN_MAKEIDR2(id) FMSTR_MSCAN_MAKEIDR2(id) 
00042     #define FMSTR_CAN_MAKEIDR3(id) FMSTR_MSCAN_MAKEIDR3(id) 
00043 
00044     #define FMSTR_CAN_TCTX FMSTR_MSCAN_TCTX 
00045     #define FMSTR_CAN_TCFG(pctx) FMSTR_MSCAN_TCFG(pctx) 
00046     #define FMSTR_CAN_TID(pctx, idr0, idr1, idr2, idr3) FMSTR_MSCAN_TID(pctx, idr0, idr1, idr2, idr3) 
00047     #define FMSTR_CAN_TLEN(pctx, len) FMSTR_MSCAN_TLEN(pctx, len) 
00048     #define FMSTR_CAN_TPRI(pctx, txPri) FMSTR_MSCAN_TPRI(pctx, txPri) 
00049     #define FMSTR_CAN_PUTBYTE(pctx, dataByte) FMSTR_MSCAN_PUTBYTE(pctx, dataByte) 
00050     #define FMSTR_CAN_TX(pctx) FMSTR_MSCAN_TX(pctx) 
00051 
00052     #define FMSTR_CAN_RCTX FMSTR_MSCAN_RCTX 
00053     #define FMSTR_CAN_RINIT(idr0, idr1, idr2, idr3) FMSTR_MSCAN_RINIT(idr0, idr1, idr2, idr3) 
00054     #define FMSTR_CAN_TINIT(idr0, idr1, idr2, idr3) FMSTR_MSCAN_TINIT(idr0, idr1, idr2, idr3)
00055     #define FMSTR_CAN_RCFG() FMSTR_MSCAN_RCFG() 
00056     #define FMSTR_CAN_RX(pctx) FMSTR_MSCAN_RX(pctx) 
00057     #define FMSTR_CAN_TEST_RIDR(pctx, idr0, idr1, idr2, idr3) FMSTR_MSCAN_TEST_RIDR(pctx, idr0, idr1, idr2, idr3) 
00058     #define FMSTR_CAN_RLEN(pctx) FMSTR_MSCAN_RLEN(pctx) 
00059     #define FMSTR_CAN_GETBYTE(pctx) FMSTR_MSCAN_GETBYTE(pctx) 
00060     #define FMSTR_CAN_RFINISH(pctx) FMSTR_MSCAN_RFINISH(pctx) 
00061 
00062 #elif FMSTR_USE_FLEXCAN
00063 
00064     #define FMSTR_CAN_ETXI() FMSTR_FCAN_ETXI() 
00065     #define FMSTR_CAN_DTXI() FMSTR_FCAN_DTXI() 
00066     #define FMSTR_CAN_ERXI() FMSTR_FCAN_ERXI() 
00067     #define FMSTR_CAN_DRXI() FMSTR_FCAN_DRXI() 
00068     #define FMSTR_CAN_TEST_RXFLG() FMSTR_FCAN_TEST_RXFLG() 
00069     #define FMSTR_CAN_CLEAR_RXFLG() FMSTR_FCAN_CLEAR_RXFLG() 
00070     #define FMSTR_CAN_TEST_TXFLG() FMSTR_FCAN_TEST_TXFLG() 
00071     #define FMSTR_CAN_GET_MBSTATUS() FMSTR_FCAN_GET_MBSTATUS()
00072     #define FMSTR_CAN_MAKEIDR0(id) FMSTR_FCAN_MAKEIDR0(id) 
00073     #define FMSTR_CAN_MAKEIDR1(id) FMSTR_FCAN_MAKEIDR1(id) 
00074     #define FMSTR_CAN_MAKEIDR2(id) FMSTR_FCAN_MAKEIDR2(id) 
00075     #define FMSTR_CAN_MAKEIDR3(id) FMSTR_FCAN_MAKEIDR3(id) 
00076 
00077     #define FMSTR_CAN_TCTX FMSTR_FCAN_TCTX 
00078     #define FMSTR_CAN_TCFG(pctx) FMSTR_FCAN_TCFG(pctx) 
00079     #define FMSTR_CAN_TID(pctx, idr0, idr1, idr2, idr3) FMSTR_FCAN_TID(pctx, idr0, idr1, idr2, idr3) 
00080     #define FMSTR_CAN_TLEN(pctx, len) FMSTR_FCAN_TLEN(pctx, len) 
00081     #define FMSTR_CAN_TPRI(pctx, txPri) FMSTR_FCAN_TPRI(pctx, txPri) 
00082     #define FMSTR_CAN_PUTBYTE(pctx, dataByte) FMSTR_FCAN_PUTBYTE(pctx, dataByte) 
00083     #define FMSTR_CAN_TX(pctx) FMSTR_FCAN_TX(pctx) 
00084 
00085     #define FMSTR_CAN_RCTX FMSTR_FCAN_RCTX 
00086     #define FMSTR_CAN_RINIT(idr0, idr1, idr2, idr3) FMSTR_FCAN_RINIT(idr0, idr1, idr2, idr3) 
00087     #define FMSTR_CAN_TINIT(idr0, idr1, idr2, idr3) FMSTR_FCAN_TINIT(idr0, idr1, idr2, idr3)
00088     #define FMSTR_CAN_RCFG() FMSTR_FCAN_RCFG() 
00089     #define FMSTR_CAN_RX(pctx) FMSTR_FCAN_RX(pctx) 
00090     #define FMSTR_CAN_TEST_RIDR(pctx, idr0, idr1, idr2, idr3) FMSTR_FCAN_TEST_RIDR(pctx, idr0, idr1, idr2, idr3) 
00091     #define FMSTR_CAN_RLEN(pctx) FMSTR_FCAN_RLEN(pctx) 
00092     #define FMSTR_CAN_GETBYTE(pctx) FMSTR_FCAN_GETBYTE(pctx) 
00093     #define FMSTR_CAN_RFINISH(pctx) FMSTR_FCAN_RFINISH(pctx) 
00094 
00095 #else
00096 #error CAN interface undefined
00097 #endif
00098 
00099 /***********************************
00100 *  local variables 
00101 ***********************************/
00102 
00103 /* FreeMASTER communication buffer (in/out) plus the STS and LEN bytes */
00104 static FMSTR_BCHR pcm_pCommBuffer[FMSTR_COMM_BUFFER_SIZE+3];    
00105 
00106 /* FreeMASTER runtime flags */
00107 /*lint -e{960} using union */
00108 static volatile union 
00109 {
00110     FMSTR_FLAGS all;
00111     
00112     struct 
00113     {
00114         unsigned bTxActive : 1;        /* response is just being transmitted */
00115         unsigned bTxFirst : 1;         /* first frame to be send out */
00116         unsigned bRxActive : 1;        /* just in the middle of receiving (fragmented) frame */
00117         unsigned bRxFirst : 1;         /* expecting the first frame (FST) */
00118         unsigned bRxTgl1 : 1;          /* expecting TGL=1 in next frame */
00119         unsigned bRxFrameReady : 1;    /* frame received (waiting to be handled in poll) */
00120         unsigned bRxSpecial : 1;       /* special command received (not passed to ProtocolDecode) */
00121         
00122     } flg;
00123     
00124 } pcm_wFlags;
00125 
00126 /* receive and transmit buffers and counters */
00127 static FMSTR_SIZE8 pcm_nTxTodo;        /* transmission to-do counter (0 when tx is idle) */
00128 static FMSTR_BPTR  pcm_pTxBuff;        /* pointer to next byte to transmit */
00129 static FMSTR_SIZE8 pcm_nRxCtr;         /* how many bytes received (total across all fragments) */
00130 static FMSTR_BPTR  pcm_pRxBuff;        /* pointer to next free place in RX buffer */
00131 static FMSTR_BCHR  pcm_nRxErr;         /* error raised during receive process */
00132 static FMSTR_BCHR  pcm_nRxCheckSum;    /* checksum of data being received */
00133 static FMSTR_U8    pcm_uTxCtlByte;
00134 static FMSTR_U8    pcm_uTxFrmCtr;      /* TX CAN frame counter (within one FreeMASTER frame) */
00135 
00136 #if FMSTR_CAN_CMDID_DYNAMIC
00137     static FMSTR_U8 pcm_cmdIdr[4] = 
00138     { 
00139         FMSTR_CAN_MAKEIDR0(FMSTR_CAN_CMDID),
00140         FMSTR_CAN_MAKEIDR1(FMSTR_CAN_CMDID),
00141         FMSTR_CAN_MAKEIDR2(FMSTR_CAN_CMDID),
00142         FMSTR_CAN_MAKEIDR3(FMSTR_CAN_CMDID)
00143     };
00144     
00145     #define FMSTR_CAN_CMDID_IDR0 pcm_cmdIdr[0]
00146     #define FMSTR_CAN_CMDID_IDR1 pcm_cmdIdr[1]
00147     #define FMSTR_CAN_CMDID_IDR2 pcm_cmdIdr[2]
00148     #define FMSTR_CAN_CMDID_IDR3 pcm_cmdIdr[3]
00149 #else
00150     #define FMSTR_CAN_CMDID_IDR0 FMSTR_CAN_MAKEIDR0(FMSTR_CAN_CMDID)
00151     #define FMSTR_CAN_CMDID_IDR1 FMSTR_CAN_MAKEIDR1(FMSTR_CAN_CMDID)
00152     #define FMSTR_CAN_CMDID_IDR2 FMSTR_CAN_MAKEIDR2(FMSTR_CAN_CMDID)
00153     #define FMSTR_CAN_CMDID_IDR3 FMSTR_CAN_MAKEIDR3(FMSTR_CAN_CMDID)
00154 #endif
00155 
00156 #if FMSTR_CAN_RESPID_DYNAMIC
00157     static FMSTR_U8 pcm_respIdr[4] = 
00158     { 
00159         FMSTR_CAN_MAKEIDR0(FMSTR_CAN_CMDID),
00160         FMSTR_CAN_MAKEIDR1(FMSTR_CAN_CMDID),
00161         FMSTR_CAN_MAKEIDR2(FMSTR_CAN_CMDID),
00162         FMSTR_CAN_MAKEIDR3(FMSTR_CAN_CMDID)
00163     };
00164     
00165     #define FMSTR_CAN_RESPID_IDR0 pcm_respIdr[0]
00166     #define FMSTR_CAN_RESPID_IDR1 pcm_respIdr[1]
00167     #define FMSTR_CAN_RESPID_IDR2 pcm_respIdr[2]
00168     #define FMSTR_CAN_RESPID_IDR3 pcm_respIdr[3]
00169 #else
00170     #define FMSTR_CAN_RESPID_IDR0 FMSTR_CAN_MAKEIDR0(FMSTR_CAN_RESPID)
00171     #define FMSTR_CAN_RESPID_IDR1 FMSTR_CAN_MAKEIDR1(FMSTR_CAN_RESPID)
00172     #define FMSTR_CAN_RESPID_IDR2 FMSTR_CAN_MAKEIDR2(FMSTR_CAN_RESPID)
00173     #define FMSTR_CAN_RESPID_IDR3 FMSTR_CAN_MAKEIDR3(FMSTR_CAN_RESPID)
00174 #endif
00175 
00176 /***********************************
00177 *  local function prototypes
00178 ***********************************/
00179 
00180 static void FMSTR_Listen(void);
00181 static void FMSTR_RxDone(void);
00182 static void FMSTR_SendError(FMSTR_BCHR nErrCode);
00183 
00184 /**************************************************************************/
00190 void FMSTR_InitCan(void)
00191 {   
00192     /* initialize all state variables */
00193     pcm_wFlags.all = 0U;
00194     pcm_nTxTodo = 0U;
00195 
00196     /* configure CAN receiving (used by FlexCAN to setup MB) */
00197     FMSTR_CAN_RINIT(FMSTR_CAN_CMDID_IDR0, FMSTR_CAN_CMDID_IDR1, \
00198                     FMSTR_CAN_CMDID_IDR2, FMSTR_CAN_CMDID_IDR3);
00199     
00200     /* configure CAN transmitting (used by FlexCAN to setup MB) */
00201     FMSTR_CAN_TINIT(FMSTR_CAN_CMDID_IDR0, FMSTR_CAN_CMDID_IDR1, \
00202                     FMSTR_CAN_CMDID_IDR2, FMSTR_CAN_CMDID_IDR3);
00203 
00204     /* start listening for commands */
00205     FMSTR_Listen();
00206 }
00207 
00208 void FMSTR_SetCanCmdID(FMSTR_U32 canID)
00209 {   
00210 #if FMSTR_CAN_CMDID_DYNAMIC
00211     pcm_cmdIdr[0] = FMSTR_CAN_MAKEIDR0(canID);
00212     pcm_cmdIdr[1] = FMSTR_CAN_MAKEIDR1(canID);
00213     pcm_cmdIdr[2] = FMSTR_CAN_MAKEIDR2(canID);
00214     pcm_cmdIdr[3] = FMSTR_CAN_MAKEIDR3(canID);
00215 #else
00216     FMSTR_UNUSED(canID);    
00217 #endif
00218 }
00219 
00220 void FMSTR_SetCanRespID(FMSTR_U32 canID)
00221 {   
00222 #if FMSTR_CAN_RESPID_DYNAMIC
00223     pcm_respIdr[0] = FMSTR_CAN_MAKEIDR0(canID);
00224     pcm_respIdr[1] = FMSTR_CAN_MAKEIDR1(canID);
00225     pcm_respIdr[2] = FMSTR_CAN_MAKEIDR2(canID);
00226     pcm_respIdr[3] = FMSTR_CAN_MAKEIDR3(canID);
00227 #else
00228     FMSTR_UNUSED(canID);    
00229 #endif
00230 }
00231 
00232 /**************************************************************************/
00238 static void FMSTR_Listen(void)
00239 {
00240     /* disable transmitter state machine */
00241     pcm_wFlags.flg.bTxActive = 0U;
00242     
00243     /* wait for first frame */
00244     pcm_wFlags.flg.bRxFrameReady = 0U;
00245     pcm_wFlags.flg.bRxFirst = 1U;
00246     pcm_wFlags.flg.bRxActive = 1U;
00247 
00248     /* enable CAN receiving */
00249     FMSTR_CAN_RCFG();
00250     
00251 #if FMSTR_LONG_INTR || FMSTR_SHORT_INTR
00252     FMSTR_CAN_ERXI();
00253 #endif
00254 }
00255 
00256 /**************************************************************************/
00264 static void FMSTR_SendError(FMSTR_BCHR nErrCode)
00265 {
00266     /* fill & send single-byte response */
00267     *pcm_pCommBuffer = nErrCode;
00268     FMSTR_SendResponse(pcm_pCommBuffer, 1U);
00269 }
00270 
00271 /**************************************************************************/
00283 void FMSTR_SendResponse(FMSTR_BPTR pResponse, FMSTR_SIZE8 nLength)
00284 {
00285     FMSTR_U16 chSum = 0U;
00286     FMSTR_U8 i, c;
00287 
00288     /* remember the buffer to be sent */
00289     pcm_pTxBuff = pResponse;
00290     
00291     /* status byte and data are already there, compute checksum only     */
00292     for (i=0U; i<nLength; i++)
00293     {
00294         c = 0U;
00295         pResponse = FMSTR_ValueFromBuffer8(&c, pResponse);
00296         /* add character to checksum */
00297         chSum += c;
00298         /* prevent saturation to happen on DSP platforms */
00299         chSum &= 0xffU;
00300     }
00301     
00302     /* store checksum after the message */
00303     pResponse = FMSTR_ValueToBuffer8(pResponse, (FMSTR_U8) (((FMSTR_U16)~(chSum)) + 1U));
00304 
00305     /* send the message and the checksum */
00306     pcm_nTxTodo = (FMSTR_SIZE8) (nLength + 1U); 
00307 
00308     /* now transmitting the response */
00309     pcm_wFlags.flg.bTxActive = 1U;
00310     pcm_wFlags.flg.bTxFirst = 1U;
00311 
00312     /* enable TX interrupt */
00313 #if FMSTR_LONG_INTR || FMSTR_SHORT_INTR
00314     FMSTR_CAN_ETXI();
00315 #endif
00316 #if (FMSTR_SHORT_INTR) && (FMSTR_USE_FLEXCAN)
00317     FMSTR_ProcessCanTx();
00318 #endif
00319 }
00320 
00321 /**************************************************************************/
00333 FMSTR_BOOL FMSTR_TxCan(void)
00334 {
00335     FMSTR_U8 ch;
00336     FMSTR_CAN_TCTX tctx;
00337     FMSTR_SIZE8 len = pcm_nTxTodo;
00338     
00339     if(!pcm_wFlags.flg.bTxActive || !pcm_nTxTodo)
00340         return FMSTR_FALSE;
00341 
00342     if(len > 7)
00343         len = 7;
00344     
00345     /* first byte is control */
00346     if(pcm_wFlags.flg.bTxFirst)
00347     {
00348         /* the first frame and the length*/
00349         pcm_uTxCtlByte = (FMSTR_U8) (FMSTR_CANCTL_FST | len);
00350         pcm_uTxFrmCtr = 0U;
00351         pcm_wFlags.flg.bTxFirst = 0U;
00352     }
00353     else
00354     {
00355         /* the next frame */
00356         pcm_uTxCtlByte &= ~(FMSTR_CANCTL_FST | FMSTR_CANCTL_LEN_MASK);
00357         pcm_uTxCtlByte ^= FMSTR_CANCTL_TGL;
00358         pcm_uTxCtlByte |= len;
00359         pcm_uTxFrmCtr++;
00360     }
00361 
00362     /* prepare transmit buffer */
00363     FMSTR_CAN_TCFG(&tctx);
00364 
00365     /* set transmit priority and ID */
00366     FMSTR_CAN_TPRI(&tctx, pcm_uTxFrmCtr);
00367     FMSTR_CAN_TID(&tctx, FMSTR_CAN_RESPID_IDR0,
00368         FMSTR_CAN_RESPID_IDR1, FMSTR_CAN_RESPID_IDR2, FMSTR_CAN_RESPID_IDR3);
00369 
00370     /* is it the last frame? */
00371     pcm_nTxTodo -= len;
00372     if(!pcm_nTxTodo)
00373         pcm_uTxCtlByte |= FMSTR_CANCTL_LST; 
00374 
00375     /* set frame len */
00376     FMSTR_CAN_TLEN(&tctx, (FMSTR_U8) (len+1));
00377 
00378     /* put control byte */
00379     FMSTR_CAN_PUTBYTE(&tctx, pcm_uTxCtlByte);
00380 
00381     /* put data part */
00382     while(len--)
00383     {
00384         pcm_pTxBuff = FMSTR_ValueFromBuffer8(&ch, pcm_pTxBuff);
00385         FMSTR_CAN_PUTBYTE(&tctx, ch);
00386     }
00387 
00388     /* submit frame for transmission */
00389     FMSTR_CAN_TX(&tctx);
00390 
00391     /* if the full frame is safe in tx buffer(s), release the received command */
00392     if(!pcm_nTxTodo)
00393     {
00394         /* no more transmitting */        
00395         pcm_wFlags.flg.bTxActive = 0U;
00396 
00397         /* start listening immediately (also frees the last received frame) */
00398         FMSTR_Listen();
00399     }
00400 
00401     /* returning TRUE, frame was sent */
00402     return FMSTR_TRUE;
00403 }
00404 
00405 
00406 /**************************************************************************/
00414 FMSTR_BOOL FMSTR_RxCan(void)
00415 {
00416     FMSTR_CAN_RCTX rctx;
00417     FMSTR_SIZE8 len;
00418     FMSTR_U8 ctl, ch;
00419 
00420     if(!pcm_wFlags.flg.bRxActive)
00421         return FMSTR_FALSE;
00422 
00423     /* last FreeMASTER frame not yet handled */
00424     if(pcm_wFlags.flg.bRxFrameReady)
00425         return FMSTR_FALSE;
00426 
00427     /* get the frame */
00428     FMSTR_CAN_RX(&rctx);
00429 
00430     /* test message ID is it matches the CMDID */
00431     if(!FMSTR_CAN_TEST_RIDR(&rctx, FMSTR_CAN_CMDID_IDR0, FMSTR_CAN_CMDID_IDR1, 
00432         FMSTR_CAN_CMDID_IDR2, FMSTR_CAN_CMDID_IDR3))
00433     {
00434         FMSTR_CAN_RFINISH(&rctx);
00435         return FMSTR_FALSE;
00436     }
00437 
00438     /* get the first (control) byte */
00439     ctl = FMSTR_CAN_GETBYTE(&rctx);
00440 
00441     /* should be master-to-slave (otherwise perhaps a self-received frame) */
00442     if(!(ctl & FMSTR_CANCTL_M2S))
00443         goto frame_contd;
00444 
00445     /* first frame resets the state machine */
00446     if((ctl & FMSTR_CANCTL_FST) || pcm_wFlags.flg.bRxFirst)
00447     {
00448         if(!(ctl & FMSTR_CANCTL_FST) || /* must be the first frame! */
00449             (ctl & FMSTR_CANCTL_TGL))   /* TGL must be zero! */
00450         {
00451             /* frame is ours, but we ignore it */
00452             goto frame_contd;
00453         }
00454 
00455         /* now receive the rest of bigger FreeMASTER frame */
00456         pcm_wFlags.flg.bRxFirst = 0U;
00457         pcm_wFlags.flg.bRxTgl1 = 1U;
00458 
00459         /* special command? */
00460         if(ctl & FMSTR_CANCTL_SPC)
00461             pcm_wFlags.flg.bRxSpecial = 1U;
00462         else
00463             pcm_wFlags.flg.bRxSpecial = 0U;
00464 
00465         /* start receiving the frame */
00466         pcm_pRxBuff = pcm_pCommBuffer;
00467         pcm_nRxCheckSum = 0;
00468         pcm_nRxCtr = 0;
00469         pcm_nRxErr = 0;
00470     }
00471     else
00472     {
00473         /* toggle bit should match */
00474         if((pcm_wFlags.flg.bRxTgl1 && !(ctl & FMSTR_CANCTL_TGL)) ||
00475            (!pcm_wFlags.flg.bRxTgl1 && (ctl & FMSTR_CANCTL_TGL)))
00476         {
00477             /* invalid sequence detected */
00478             pcm_nRxErr = FMSTR_STC_CANTGLERR;
00479             goto frame_done;
00480         }
00481 
00482         /* expect next frame toggled again */
00483         pcm_wFlags.flg.bRxTgl1 ^= 1U;
00484     }
00485 
00486     /* frame is valid, get the data */
00487     len = (FMSTR_SIZE8) (ctl & FMSTR_CANCTL_LEN_MASK);
00488 
00489     /* sanity check of the len field */
00490     if(len >= FMSTR_CAN_RLEN(&rctx))
00491     {
00492         /* invalid frame length, re-start receiving */
00493         pcm_nRxErr = FMSTR_STC_CANMSGERR;
00494         goto frame_done;
00495     }
00496 
00497     /* will data fit? */
00498     if((pcm_nRxCtr+len) > FMSTR_COMM_BUFFER_SIZE)
00499     {
00500         /* this frame must be ignored, start receiving again */
00501         pcm_nRxErr = FMSTR_STC_CANMSGERR;
00502         goto frame_done;
00503     }
00504 
00505     /* okay, receive all data bytes */
00506     pcm_nRxCtr += len;
00507     while(len--)
00508     {
00509         ch = FMSTR_CAN_GETBYTE(&rctx);
00510         pcm_pRxBuff = FMSTR_ValueToBuffer8(pcm_pRxBuff, ch);
00511         pcm_nRxCheckSum += ch;
00512     }
00513 
00514     /* was it the last frame? */    
00515     if(!(ctl & FMSTR_CANCTL_LST))
00516         goto frame_contd;
00517 
00518     /* done with the FreeMASTER frame, it will be handled later in RxDone */
00519 frame_done:
00520     /* disable receiver so it does not corrupt the frame until it is handled */
00521     pcm_wFlags.flg.bRxActive = 0;
00522     /* frame received. Checksum and frame will be checked later in RxDone */
00523     pcm_wFlags.flg.bRxFrameReady = 1U;
00524 
00525     /* frame will continue by next chunk next time */
00526 frame_contd:
00527     FMSTR_CAN_RFINISH(&rctx);
00528     return FMSTR_TRUE;
00529 }
00530 
00531 /**************************************************************************/
00537 static void FMSTR_RxDone(void)
00538 {
00539     /* frame really here? */
00540     if(!pcm_wFlags.flg.bRxFrameReady)
00541         return ;
00542 
00543     /* acknowledge the flag, we're going to process the frame now */
00544     pcm_wFlags.flg.bRxFrameReady = 0U;
00545 
00546     /* any fragmentation error detected during the receive process? */
00547     if(!pcm_nRxErr)
00548     {
00549         /* check for our standard frame errors */
00550 
00551         /* checksum should be zero */
00552         if(pcm_nRxCheckSum)
00553         {
00554             pcm_nRxErr = FMSTR_STC_CMDCSERR;
00555         }
00556         /* checksum okay, check frame length */
00557         else
00558         {
00559             FMSTR_BPTR pFrame = pcm_pCommBuffer;
00560             FMSTR_BCHR len;
00561 
00562             pFrame = FMSTR_ValueFromBuffer8(&len, pFrame);
00563 
00564             /* fast command? */
00565             if((len & FMSTR_FASTCMD) == FMSTR_FASTCMD)
00566             {
00567                 /* get length */
00568                 len = (FMSTR_BCHR)((len & FMSTR_FASTCMD_DATALEN_MASK) >> FMSTR_FASTCMD_DATALEN_SHIFT);
00569 
00570                 /* add command-byte and checksum (are included in the nRxCtr) */
00571                 len += 2;
00572             }
00573             /* std command */
00574             else
00575             {
00576                 /* get length */
00577                 pFrame = FMSTR_ValueFromBuffer8(&len, pFrame);
00578 
00579                 /* add command-byte, length and checksum (are included in the nRxCtr) */
00580                 len += 3;
00581             }
00582             
00583             /* now the len received should match the data bytes received */
00584             if(pcm_nRxCtr != len)
00585                 pcm_nRxErr = FMSTR_STC_CMDCSERR;
00586         }
00587     }
00588 
00589     /* any error? */
00590     if(pcm_nRxErr)
00591     {
00592         FMSTR_SendError(FMSTR_STC_CMDCSERR);
00593     }
00594     /* no error */
00595     else 
00596     {
00597         /* special CAN command? for our layer */
00598         if(pcm_wFlags.flg.bRxSpecial)
00599         {
00600             FMSTR_BPTR pFrame = pcm_pCommBuffer;
00601             FMSTR_BCHR c;
00602 
00603             /* get the command */            
00604             FMSTR_ValueFromBuffer8(&c, pFrame);
00605 
00606             switch(c)
00607             {
00608             case FMSTR_CANSPC_PING:
00609                 FMSTR_SendError(FMSTR_STS_OK);
00610                 break;
00611 
00612             default:
00613                 /* unknown command */
00614                 FMSTR_SendError(FMSTR_STC_INVCMD);
00615             }
00616         }
00617         /* standard FreeMASTER command to be passed above */
00618         else
00619         {
00620             /* decode and handle frame by SCI classic driver */
00621             if(!FMSTR_ProtocolDecoder(pcm_pCommBuffer))
00622             {
00623                 /* if no response was generated, start listening again, otherwise, 
00624                    the receive will be initiated after transmission  is complete in 
00625                    FMSTR_TxCan (this prevents our TX buffer to be corrupted by RX) */
00626                 FMSTR_Listen();  
00627             }
00628         }
00629     }
00630 }
00631 
00632 /**************************************************************************/
00640 void FMSTR_ProcessCanRx(void)
00641 {
00642     if(FMSTR_CAN_TEST_RXFLG())
00643     {
00644         /* process the CAN frame */ 
00645         FMSTR_RxCan();
00646 
00647         /* CAN frame handled, release the flag */
00648         FMSTR_CAN_CLEAR_RXFLG();
00649 
00650 #if FMSTR_LONG_INTR
00651         /* handle completed frame now? (may be we're in the interrupt) */
00652         if(pcm_wFlags.flg.bRxFrameReady)
00653             FMSTR_RxDone();
00654 #endif
00655     }
00656 }
00657 
00658 /**************************************************************************/
00666 void FMSTR_ProcessCanTx(void)
00667 {
00668 #if FMSTR_USE_MSCAN
00669     /* any TX buffer available? */
00670     if(FMSTR_CAN_TEST_TXFLG())
00671     {
00672 #if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
00673         /* send one CAN frame (fills buffer and clears its TXFLG */
00674         if(!FMSTR_TxCan())
00675         {
00676             /* no more frames, disable TX Interrupt */
00677             FMSTR_CAN_DTXI();
00678         }
00679 #else
00680         /* send if you have anything to be sent */
00681         FMSTR_TxCan();
00682 #endif
00683     }
00684 #elif FMSTR_USE_FLEXCAN
00685 
00686     /* is TX buffer ready for next packet? */
00687     if((FMSTR_CAN_GET_MBSTATUS()) == FMSTR_FCANMB_CTXREADY)
00688     {
00689 #if FMSTR_SHORT_INTR || FMSTR_LONG_INTR
00690         /* send one CAN frame (fills buffer and clears its TXFLG */
00691         if(!FMSTR_TxCan())
00692         {
00693             /* no more frames, disable TX Interrupt */
00694             FMSTR_CAN_DTXI();
00695         }
00696 #else
00697         /* send if you have anything to be sent */
00698         FMSTR_TxCan();
00699 #endif
00700     }
00701 #endif
00702 }
00703 
00704 /*******************************************************************************
00705 *
00706 * @brief    API: Main "Polling" call from the application main loop
00707 *
00708 *******************************************************************************/
00709 
00710 void FMSTR_Poll(void)
00711 { 
00712     /* handle the physical CAN module */    
00713 #if FMSTR_POLL_DRIVEN
00714     FMSTR_ProcessCanRx();
00715     FMSTR_ProcessCanTx();
00716 #endif
00717 
00718 #if FMSTR_POLL_DRIVEN || FMSTR_SHORT_INTR
00719 
00720     /* except in the LONG_INTR mode, the frame gets handled here */
00721     if(pcm_wFlags.flg.bRxFrameReady)
00722         FMSTR_RxDone();
00723 #endif
00724 }
00725 
00726 #endif /* FMSTR_USE_CAN */
00727